package com.fp.m7.dao;

import java.util.Date;
import java.util.List;

import com.fp.m7.model.Account;
import com.fp.m7.model.Follow;

public class FollowDaoImpl extends BaseDaoImpl<Follow> implements FollowDao {
	
    public FollowDaoImpl() {
        super(Follow.class);
    }

    @Override
    public void follow(Account follower, Account followed) {
    	List<Follow> existing = findExistingFollows(follower, followed);

        if (existing.isEmpty()) {
            Follow follow = new Follow();
            follow.setFollower(follower);
            follow.setFollowed(followed);
            super.persist(follow);
        }
    }

    @Override
    public void unfollow(Account follower, Account followed) {
        List<Follow> existing = findExistingFollows(follower, followed);

        if (!existing.isEmpty()) {
            Date deletionDate = clock.getDate();
            for (Follow follow : existing) {
                // setting auditDD to current date means that this follow is finished
                follow.setAuditDD(deletionDate);
                super.merge(follow);
            }
        }
    }
    
    private List<Follow> findExistingFollows(Account follower, Account followed) {
    	return em.createNamedQuery("findFollowers", Follow.class) //
                .setParameter("follower", follower) //
                .setParameter("followed", followed) //
                .getResultList();
    }

    @Override
    public boolean isFollowing(Account user, Account other) {
        String query = "select count(f) from Follow f where f.follower = :follower and f.followed = :followed and f.auditDD is null";
        Long count = (Long) em.createQuery(query) //
                .setParameter("follower", user) //
                .setParameter("followed", other) //
                .getSingleResult();

        return count > 0;
    }

    @Override
    public boolean isFollowedBy(Account user, Account other) {
        return isFollowing(other, user);
    }

    @Override
    public List<Account> getFollowersForUser(Account user) {
        String query = "select f.follower from Follow f where f.followed = :user and f.auditDD is null order by f.auditCD";
        return em.createQuery(query, Account.class) //
                .setParameter("user", user) //
                .getResultList();
    }

    @Override
    public List<Account> getFollowedByUser(Account user) {
        String query = "select f.followed from Follow f where f.follower = :user and f.auditDD is null order by f.auditCD";
        return em.createQuery(query, Account.class) //
                .setParameter("user", user) //
                .getResultList();
    }

    @Override
    public int countActiveFollowers(Account followed) {
        String query = "select count(f) from Follow f where f.followed = :followed and f.auditDD is null";
        Long count = (Long) em.createQuery(query) //
                .setParameter("followed", followed) //
                .getSingleResult();

        return count.intValue();
    }

    @Override
    public int countActivelyFollowed(Account follower) {
        String query = "select count(f) from Follow f where f.follower = :follower and f.auditDD is null";
        Long count = (Long) em.createQuery(query) //
                .setParameter("follower", follower) //
                .getSingleResult();

        return count.intValue();
    }
}
